// Copyright 2023 Specter Ops, Inc.
// 
// Licensed under the Apache License, Version 2.0
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// SPDX-License-Identifier: Apache-2.0

module.exports = {
    name: `plugin-nested-workspace`,
    factory: require => ({
        hooks: {
            async setupScriptEnvironment(project, scriptEnv, makePathWrapper) {
                if (scriptEnv != null && project.configuration.get(`nodeLinker`) === `node-modules`) {
                    const path = require("path");
                    const fs = require("fs");
                    const { npath } = require("@yarnpkg/fslib");
                    const nodeModulesDir = path.resolve(project.cwd, "node_modules");
                    const stateFile = path.resolve(nodeModulesDir, ".yarn-state.yml");
                    const childWorkspaceMatches = [...project.workspacesByCwd.keys()].filter((value) => path.basename(value) === scriptEnv.npm_package_name);
                    const maybeNestedWorkspace = childWorkspaceMatches.reduce((acc, currentWorkspace) => {
                        try {
                            const nodeModulesDir = fs.readdirSync(path.resolve(currentWorkspace, "node_modules"));
                            return nodeModulesDir.length > 0;
                        } catch {
                            return acc || false;
                        }
                    }, false);


                    if (!fs.existsSync(stateFile) && maybeNestedWorkspace) {
                        console.log("State file is missing in potentially nested workspace.");
                        console.log("Generating empty state file...");

                        fs.mkdirSync(require('path').dirname(stateFile), { recursive: true });
                        fs.appendFileSync(stateFile, "# Autogenerated\n", { "flag": "w+" });
                        fs.appendFileSync(stateFile, "__metadata:\n");
                        fs.appendFileSync(stateFile, "  version: 1\n");
                        fs.appendFileSync(stateFile, "  nmMode: classic\n");
                    }

                    if (maybeNestedWorkspace) {
                        const packagePaths = childWorkspaceMatches.map((value) => path.resolve(value, "node_modules", ".bin")).join(npath.delimiter);
                        scriptEnv.PATH = packagePaths ? [packagePaths, scriptEnv.PATH].join(npath.delimiter) : scriptEnv.PATH;
                    }
                }
            }
        },
    })
};

